//
// Created by fairy on 2024/10/10.
//
/**
* @brief 中断服务例程
 * @note 用于处理各种中断回调函数，之所以不用stm32f4xx_it.c,是因为本工程是由C/C++混编，
 *      中断服务例程可能会调用到C++文件相关的代码。
 * @不详 这里发生了奇怪的事，有时候在这里定义甚至包括声明中断处理函数，但是链接时会把函数忽略，即使使用了
 *      extern "C"包含。但map文件确实没有任何相关函数符号，即使是-O0优化。编译也看了，会编译这个文件
 *      真是奇怪。难道是没有头文件的原因？但为什么EXTI0中断可以
 * @解决不详 好吧EXTI0也不可以，原因很简单，不能直接把该文件编译成静态库再取链接启动文件(除非该文件有头文件)。
 *      而是和启动文件一样，作为资源文件一起链接其他静态库
*/
#include <common_definition.h>
#include <project_config.h>
#include <stm32f4xx_hal.h>


#include <baseInit.hpp>
#include <hal.hpp>
#include <spi.hpp>
#include <usart.hpp>

#ifdef ENABLE_GUI
#include <gui.hpp>
#include <../../bsp/lcd/st7796.hpp>
#include <lvgl.h>
#endif
#ifdef ENABLE_FREERTOS
#include "cmsis_os2.h"
#endif


#define KEY_RAM (*((volatile unsigned short *) 0x6006000C))// 键盘接口地址
//extern DMA_HandleTypeDef hdma_memtomem_dma2_stream6;


/** TIM中断回调函数
 * @note 关于TIM6已经转移至timer.c里了
 * */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    //    if (htim->Instance == TIM6)
    //    {
    ////        timer6_isr();
    //    }
}


// TIM7中断处理函数
extern "C" {
void TIM7_IRQHandler()
{
    // 我把TIM7当做系统时钟，只用到了基础定时器的更新计时功能，所以并不需要判断中断源
    __HAL_TIM_CLEAR_FLAG(hal::rcc::getTIMBaseHandler(), TIM_FLAG_UPDATE);
    HAL_IncTick();
#ifdef ENABLE_GUI
    gui::control::tick_inc();
#endif
}
}
#ifdef BSP_USE_PWR
void HAL_PWR_PVDCallback(void)
{
    __HAL_PWR_CLEAR_FLAG(PWR_FLAG_PVDO);  // 清除 PVD 标志
    if (__HAL_PWR_GET_FLAG(PWR_FLAG_PVDO))// 检查是否是电压下降
    {
        // 断电时执行的代码
        //        Execute_Shutdown_Code();

        //        // 保存关键数据到后备寄存器
        //        HAL_PWR_EnableBkUpAccess(); // 允许访问后备寄存器
        //        __HAL_RCC_BKP_CLK_ENABLE(); // 启用后备寄存器时钟
        //        HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR0, 0x12345678); // 示例：保存数据
    } else
    {
        // 电压恢复时执行的代码（可选）
    }
}
#endif

/*******************************中断服务例程**************************************/

extern "C" {
void EXTI0_IRQHandler()
{
    __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_0);
}


#ifdef ENABLE_DMA_SPI
void DMA1_Stream4_IRQHandler()
{
    /* 使用HAL库预定义宏检测标志 */
    if (__HAL_DMA_GET_FLAG(hal::spi2::getDMAHandle_tx(), __HAL_DMA_GET_TC_FLAG_INDEX(hal::spi2::getDMAHandle_tx())))
    {
        // 清除传输完成标志
        __HAL_DMA_CLEAR_FLAG(hal::spi2::getDMAHandle_tx(), __HAL_DMA_GET_TC_FLAG_INDEX(hal::spi2::getDMAHandle_tx()));

        // 更新HAL状态机（关键！否则下次传输无法启动）
        hal::spi2::getDMAHandle_tx()->State = HAL_DMA_STATE_READY;
        __HAL_UNLOCK(hal::spi2::getDMAHandle_tx());

        // 直接执行后续操作（示例：关闭片选+通知渲染完成）
        hal::spi2::cs_high();
#ifdef ENABLE_GUI
        gui::control::display_flush_ready();
#endif
    }
}
#endif


/**
 * @brief DMA中断
*/
// 主打一个狂野
#define DMA2_S6CR (*((volatile uint32_t *) 0x400264A0))
// DMA中断,里面他宝贝的真啰嗦
void DMA2_Stream6_IRQHandler(void)
{
    //    /*  检查传输完成标志（TCIF）是否被设置，即是否传输完成标志位*/
    //    if (DMA2->HISR & 0x1 << 21)
    //    {
    //        DMA2->HISR &= ~(0x1 << 21);// 清除标志位
    //        // 检查中断使能标志位
    //        if (DMA2_S6CR & (DMA_IT_TC))
    //        {
    //            DMA2_S6CR &= ~(DMA_IT_TC);// 清除标志位
    //            /* Change the DMA state */
    //            hdma_memtomem_dma2_stream6.State = HAL_DMA_STATE_READY;// 不能少,因为Start_IT里需要靠它来开启
    //            /* Process Unlocked */
    //            __HAL_UNLOCK(&hdma_memtomem_dma2_stream6);// 不能少
    //        }
    // #if defined(ENABLE_DMA_SPI) && defined(ENABLE_GUI)
    //     gui::control::display_flush_ready();
    // #endif
}
}


//DMA_USART_ENABLE 里封印着ESP8266的中断回调函数

void SysTick_Handler()
{
    HAL_IncTick();
}


extern "C" {
/**
  * @brief This function handles Non maskable interrupt.
  */
void NMI_Handler(void)
{
    while (1) {
    }
}

/**
  * @brief This function handles Hard fault interrupt.
  */
void HardFault_Handler(void)
{
    while (1)
    {
        __BKPT();
    }
}

/**
  * @brief This function handles Memory management fault.
  */
void MemManage_Handler(void)
{
    while (1) {
    }
}

/**
  * @brief This function handles Pre-fetch fault, memory access fault.
  */
void BusFault_Handler(void)
{
    while (1) {
    }
}

/**
  * @brief This function handles Undefined instruction or illegal state.
  */
void UsageFault_Handler(void)
{
    while (1) {
    }
}

/**
  * @brief This function handles Debug monitor.
  */
void DebugMon_Handler(void) {}

void EXTI9_5_IRQHandler(void)
{
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_6);
}




}
